﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using SweetSQL.Data;
using System.Reflection;

namespace SweetSQL.Extensions
{
    /// <summary>
    /// Extended Linq Database class
    /// *enables generated WHERE clauses from lambda expressions
    /// </summary>
    /// <typeparam name="T">Your derived type</typeparam>
    public class DatabaseEx<T> : Database<T>, IDatabaseEx
        where T : Database<T>
    {
        /// <summary>
        /// Constructor, takes a ConnectionParameters instance
        /// </summary>
        /// <param name="parameters">Settings for building connection string</param>
        public DatabaseEx(ConnectionParameters parameters)
            : base(parameters)
        { }

        /// <summary>
        /// Gets a TableEx instance
        /// </summary>
        /// <typeparam name="TTable">Type of mapped class</typeparam>
        /// <param name="name">Name of table</param>
        /// <returns>New table instance</returns>
        protected TableEx<TTable> GetTableEx<TTable>(string name)
            where TTable : class, new()
        {
            return new TableEx<TTable>
                {
                    Database = this,
                    DatabaseEx = this,
                    TableInfo = Reflector<T>.GetTableInfo<TTable>(name),
                };
        }

        #region IDatabaseEx Members

        IEnumerable<TTable> IDatabaseEx.Where<TTable>(Table<TTable> table, Expression<Func<TTable, bool>> func)
        {
            _connectionProvider.Connect();
            using (IDbCommand command = _connectionProvider.CreateCommand(null))
            {
                WhereEvaluator<TTable> where = new WhereEvaluator<TTable>
                    {
                        Command = command,
                        Table = table,
                        SyntaxProvider = _syntaxProvider,
                        ConnectionProvider = _connectionProvider,
                    };
                where.Evaluate(func);

                command.CommandText = SqlLanguage.BuildSelect<TTable>(_syntaxProvider, table.TableInfo) + where;

                using (IDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        yield return CreateInstance<TTable>(reader, table.TableInfo);
                    }
                }
            }
        }

        #endregion
    }
}
